using System;
using System.Configuration;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using Brettle.Web.NeatHtml;
using log4net;

namespace X.Ray.Core.Framework
{
    public static class SecurityHelper
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(SecurityHelper));

        public static string PreventCrossSiteScripting(String htmlString)
        {
            String errorHeader = ResourceHelper.GetMessageTemplate("NeatHtmlValidationErrorHeader.config");
            return PreventCrossSiteScripting(htmlString, errorHeader);

        }

        public static string PreventCrossSiteScripting(String htmlString, String errorHeader)
        {
            return PreventCrossSiteScripting(htmlString, errorHeader, false);
           
        }

        public static string PreventCrossSiteScripting(String htmlString, String errorHeader, bool removeMarkupOnFailure)
        {
            // This can be disabled by setting UseNeatHtmlForXSSPrevention to "false" in appSettings.
            string useNeatHtmlXSSPrevention = ConfigurationManager.AppSettings["UseNeatHtmlForXSSPrevention"];
            bool useNeatHtml = true;
            if (useNeatHtmlXSSPrevention != null)
            {
                useNeatHtml = bool.Parse(useNeatHtmlXSSPrevention);
            }

            if (!useNeatHtml)
            {
                return htmlString.Replace("script", "s cript");
            }

            string schemaFolder = HttpContext.Current.Server.MapPath(WebUtils.GetApplicationRoot() + "/NeatHtml/schema");
            string schemaFile = Path.Combine(schemaFolder, "NeatHtml.xsd");

            XssFilter filter = XssFilter.GetForSchema(schemaFile);
            try
            {
                return filter.FilterFragment(htmlString);
            }
            catch (Exception ex)
            {
                if (removeMarkupOnFailure)
                {
                    return String.Format(@"<span style=""color: #ff0000;"">{0}</span><br />{1}", errorHeader,
                                         HttpUtility.HtmlEncode(RemoveMarkup(htmlString)));
                }
                else
                {
                    return String.Format(@"<span style=""color: #ff0000;"">{0}{1}</span>:<br />{2}", errorHeader,
                                         HttpUtility.HtmlEncode(ex.Message), HttpUtility.HtmlEncode(htmlString));
                }
            }
        }

        public static string RemoveMarkup(string text)
        {
            text = Regex.Replace(text, @"&nbsp;", " ", RegexOptions.IgnoreCase);
            return Regex.Replace(text.Replace("  ", " "), @"<.+?>", "", RegexOptions.Singleline);
        }


        public static string GetRandomASPNET20machinekey()
        {
            StringBuilder machinekey = new StringBuilder();
            string key64byte = GetRandomKey(64);
            string key32byte = GetRandomKey(32);
            machinekey.Append("<machineKey \n");
            machinekey.Append("validationKey=\"" + key64byte + "\"\n");
            machinekey.Append("decryptionKey=\"" + key32byte + "\"\n");
            machinekey.Append("validation=\"SHA1\" decryption=\"AES\"\n");
            machinekey.Append("/>\n");
            return machinekey.ToString();
        }

        

        public static string GetRandomKey(int bytelength)
        {
            byte[] buff = new byte[bytelength];
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(buff);
            StringBuilder sb = new StringBuilder(bytelength * 2);
            for (int i = 0; i < buff.Length; i++)
            {
                sb.Append(string.Format("{0:X2}", buff[i]));
            }
            return sb.ToString();
        }

        public static void DisableBrowserCache()
        {
            if (HttpContext.Current != null)
            {
                HttpContext.Current.Response.Cache.SetExpires(new DateTime(1995, 5, 6, 12, 0, 0, DateTimeKind.Utc));
                HttpContext.Current.Response.Cache.SetNoStore();
                HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
                HttpContext.Current.Response.Cache.AppendCacheExtension("post-check=0,pre-check=0");

            }
        }

        public static void DisableDownloadCache()
        {
            HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddYears(-1));

            // no-store makes firefox reload page
            // no-cache makes firefox reload page only over SSL
            // IE will fail when downloading a file over SSL if no-store or no-cache is set
            HttpBrowserCapabilities oBrowser 
                = HttpContext.Current.Request.Browser;

            if (!oBrowser.Browser.ToLower().Contains("ie"))
            {
                HttpContext.Current.Response.Cache.SetNoStore();
            }
            
            //HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);

            // private cache allows IE to download over SSL with no-store set. 
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Private);
            HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            HttpContext.Current.Response.Cache.AppendCacheExtension("post-check=0,pre-check=0");

        }

    }
}
